package com.zc.emos.wx.config.shiro;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTCreator;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.auth0.jwt.interfaces.JWTVerifier;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * @author 曾川
 * @version 1.0.0
 * @ClassName JwtUtil.java
 * @Description Jwt配置
 *
 * 通过id获取token、
 * 验证token、
 * token的生成、
 * jwt做token是，里面不要有敏感信息，或者对敏感信息单独加密，否则，会造成信息泄露
 *
 * JWT 的原理是，服务器认证以后，生成一个 JSON 对象，发回给用户。
 * 此后，用户与服务端通信的时候，都要发回这个 JSON 对象。服务器完全只靠这个对象认定用户身份。
 * 为了防止用户篡改数据，服务器在生成这个对象的时候，会加上签名。
 * 服务器就不保存任何 session 数据了，也就是说，服务器变成无状态了，从而比较容易实现扩展。
 *
 * @createTime 2021年11月25日 17:49:00
 */
@Component
@Slf4j
public class JwtUtil {

    @Value("${emos.jwt.secret}")
    private String secret; //秘钥

    @Value("${emos.jwt.expire}")
    private int expire; //过期时间


    /*通过传入的userid，创建、生成token，createToken用于生成token，需要三部分，userid，加密算法，过期时间*/
    public String createToken(int userId) {
        //计算过期日期，定义过五天之后过期
        DateTime date = DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, 5);
        /**使用了HMAC256加密算法。
         * secret是用来加密数字签名的密钥，secret是个密钥*/
        Algorithm algorithm = Algorithm.HMAC256(secret);//密钥封装成加密算法，
        JWTCreator.Builder builder = JWT.create();//创建内部类对象
        String token = builder.withClaim("userId", userId).withExpiresAt(date).sign(algorithm);//绑定id，时间，算法
        return token;
    }

    /*根据token获取id*/
    public int getUserId(String token) {
        DecodedJWT jwt = JWT.decode(token);//解码
        int userId = jwt.getClaim("userId").asInt();//从令牌字符串中反向获取id
        return userId;
    }

    /*验证token，verify（)是为了校验签名是否被篡改*/
    public void verifierToken(String token) {
        Algorithm algorithm = Algorithm.HMAC256(secret);//传入参数token，创建算法对象，密钥加密
        JWTVerifier verifier = JWT.require(algorithm).build();//构造验证对象
        verifier.verify(token);//验证
    }
}
